package com.wenx.v3auth.service;

import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Optional;

/**
 * 令牌刷新服务
 * 负责定期清理过期令牌和维护缓存一致性
 * 优化版本：使用JdbcOAuth2AuthorizationService，无SQL代码
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class V3TokenRefreshService {

    @Resource
    private V3TokenCacheService tokenCacheService;

    /**
     * 统一的定时清理和刷新方法
     * 每10分钟执行一次，根据不同存储方式进行处理
     */
    @Scheduled(fixedRate = 10 * 60 * 1000) // 10分钟
    @Transactional
    public void refreshAndCleanupTokens() {
        try {
            log.info("开始执行令牌刷新和清理任务...");
            
            // 使用优化的缓存服务进行清理
            CleanupResult result = performCleanup();
            
            log.info("令牌刷新和清理任务完成 - 缓存清理完成，刷新了即将过期的令牌");
            
        } catch (Exception e) {
            log.error("执行令牌刷新和清理任务时发生错误", e);
        }
    }

    /**
     * 执行清理操作
     * 优化的清理逻辑，避免重复的if-else
     */
    private CleanupResult performCleanup() {
        // 1. 清理Redis缓存中的过期数据
        tokenCacheService.cleanupExpiredCache();
        
        // 2. 刷新即将过期的活跃令牌缓存
        tokenCacheService.refreshExpiringTokenCache(15, Duration.ofHours(2));
        
        return new CleanupResult(true);
    }

    /**
     * 手动触发完整的缓存清理
     */
    public void manualCleanupCache() {
        log.info("手动触发缓存清理...");
        refreshAndCleanupTokens();
        log.info("手动缓存清理完成");
    }

    /**
     * 获取缓存统计信息 - 直接从优化的缓存服务获取
     */
    public CacheStatistics getCacheStatistics() {
        return Optional.of(tokenCacheService.getCacheStatistics())
            .map(this::mapToCacheStatistics)
            .orElse(createEmptyStatistics("获取统计信息失败"));
    }

    /**
     * 映射缓存统计信息
     */
    private CacheStatistics mapToCacheStatistics(V3TokenCacheService.CacheStatistics cacheStats) {
        return CacheStatistics.builder()
            .cachedAuthorizations(cacheStats.authorizationCacheCount())
            .cachedTokenMappings(cacheStats.totalTokenMappings())
            .accessTokenMappings(cacheStats.accessTokenMappings())
            .refreshTokenMappings(cacheStats.refreshTokenMappings())
            .codeMappings(cacheStats.codeMappings())
            .databaseAuthorizations(cacheStats.databaseAuthorizations())
            .activeTokens(cacheStats.activeTokens())
            .lastCleanupTime(LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME))
            .build();
    }

    /**
     * 创建空的统计信息
     */
    private CacheStatistics createEmptyStatistics(String errorMessage) {
        return CacheStatistics.builder()
            .cachedAuthorizations(0)
            .cachedTokenMappings(0)
            .accessTokenMappings(0)
            .refreshTokenMappings(0)
            .codeMappings(0)
            .databaseAuthorizations(0)
            .activeTokens(0)
            .lastCleanupTime("错误: " + errorMessage)
            .build();
    }

    /**
     * 清理结果记录
     */
    private record CleanupResult(boolean success) {}

    /**
     * 缓存统计信息数据类
     */
    public static class CacheStatistics {
        private int cachedAuthorizations;
        private int cachedTokenMappings;
        private int accessTokenMappings;
        private int refreshTokenMappings;
        private int codeMappings;
        private int databaseAuthorizations;
        private int activeTokens;
        private String lastCleanupTime;

        public static CacheStatisticsBuilder builder() {
            return new CacheStatisticsBuilder();
        }

        public static class CacheStatisticsBuilder {
            private int cachedAuthorizations;
            private int cachedTokenMappings;
            private int accessTokenMappings;
            private int refreshTokenMappings;
            private int codeMappings;
            private int databaseAuthorizations;
            private int activeTokens;
            private String lastCleanupTime;

            public CacheStatisticsBuilder cachedAuthorizations(int cachedAuthorizations) {
                this.cachedAuthorizations = cachedAuthorizations;
                return this;
            }

            public CacheStatisticsBuilder cachedTokenMappings(int cachedTokenMappings) {
                this.cachedTokenMappings = cachedTokenMappings;
                return this;
            }

            public CacheStatisticsBuilder accessTokenMappings(int accessTokenMappings) {
                this.accessTokenMappings = accessTokenMappings;
                return this;
            }

            public CacheStatisticsBuilder refreshTokenMappings(int refreshTokenMappings) {
                this.refreshTokenMappings = refreshTokenMappings;
                return this;
            }

            public CacheStatisticsBuilder codeMappings(int codeMappings) {
                this.codeMappings = codeMappings;
                return this;
            }

            public CacheStatisticsBuilder databaseAuthorizations(int databaseAuthorizations) {
                this.databaseAuthorizations = databaseAuthorizations;
                return this;
            }

            public CacheStatisticsBuilder activeTokens(int activeTokens) {
                this.activeTokens = activeTokens;
                return this;
            }

            public CacheStatisticsBuilder lastCleanupTime(String lastCleanupTime) {
                this.lastCleanupTime = lastCleanupTime;
                return this;
            }

            public CacheStatistics build() {
                CacheStatistics stats = new CacheStatistics();
                stats.cachedAuthorizations = this.cachedAuthorizations;
                stats.cachedTokenMappings = this.cachedTokenMappings;
                stats.accessTokenMappings = this.accessTokenMappings;
                stats.refreshTokenMappings = this.refreshTokenMappings;
                stats.codeMappings = this.codeMappings;
                stats.databaseAuthorizations = this.databaseAuthorizations;
                stats.activeTokens = this.activeTokens;
                stats.lastCleanupTime = this.lastCleanupTime;
                return stats;
            }
        }

        // Getters
        public int getCachedAuthorizations() { return cachedAuthorizations; }
        public int getCachedTokenMappings() { return cachedTokenMappings; }
        public int getAccessTokenMappings() { return accessTokenMappings; }
        public int getRefreshTokenMappings() { return refreshTokenMappings; }
        public int getCodeMappings() { return codeMappings; }
        public int getDatabaseAuthorizations() { return databaseAuthorizations; }
        public int getActiveTokens() { return activeTokens; }
        public String getLastCleanupTime() { return lastCleanupTime; }
    }
} 